﻿using CubeCube.World;
using CubeCube.Utils;
using CubeCube.Sector;
using CubeCube.Tile;
using CubeCube.Configuration;
using CubeCube.World.Generator;
using System.Collections.Generic;
using System.IO;

namespace CubeCube.Chunk
{
    public class ChunkManager
    {
        public const string CHUNK_FILE_NAME = "chunks";
        private string chunkFilePath = "";
        public string CHUNK_FILE_PATH
        {
            get
            {
                if(chunkFilePath == "")
                {
                    chunkFilePath = world.worldName + Path.DirectorySeparatorChar + CHUNK_FILE_NAME;
                }
                return chunkFilePath;
            }
        }

        public CubeWorld world;
        public List<Chunk> chunks;
        public List<Chunk> cachechunks;
        public ConfigWorldGenerator generatorConfig;

        private IVisibleChunksStrategies chunkStrategies;
        private IChunkGraphics chunkGraphics;
        

        public ChunkManager(CubeWorld cubeWorld, IChunkGraphics chunkGraphics, IVisibleChunksStrategies updateStrategies)
        {
            this.world = cubeWorld;
            this.chunks = new List<Chunk>();
            this.cachechunks = new List<Chunk>();
            this.chunkGraphics = chunkGraphics;
            this.chunkStrategies = updateStrategies;
        }

        //生成
        public GeneratorProcess Generate(ConfigWorldGenerator generator)
        {
            this.generatorConfig = generator;
            return chunkStrategies.Genrator(this);
        }

        public Chunk CreateChunk(IndexPosition worldOffset)
        {
            Chunk chunk = new Chunk(world, worldOffset);  //TODO: 这里使用对象池优化
            chunkGraphics.Create(chunk);
            return chunk;
        }

        public void DestroyChunk(Chunk chunk)
        {
            chunkGraphics.Destroy(chunk);
        }

        public Chunk GetChunk(IndexPosition tilePosition)
        {
            for (int i = 0; i < chunks.Count; ++i)
            {
                if (chunks[i].ContainTilePosition(tilePosition))
                {
                    return chunks[i];
                }
            }
            return null;
        }

        public SectorManager GetSectorManager(IndexPosition tilePosition)
        {
            Chunk chunk = GetChunk(tilePosition);
            if(chunk == null)
            {
                return null;
            }
            return chunk.sectorManager;
        }

        public TileManager GetTileManager(IndexPosition tilePosition)
        {
            Chunk chunk = GetChunk(tilePosition);
            if (chunk == null)
            {
                return null;
            }
            return chunk.tileManager;
        }


        public void Update(float deltaTime)
        {
            //根据玩家的位置 去更新chunk
            chunkStrategies.Update(this, chunks, cachechunks);

            //更新chunk
            for(int i = 0; i < chunks.Count; ++i)
            {
                chunks[i].Update(deltaTime);
            }
        }

        //得到此时的border
        public int GetMinXBorder()
        {
            if (chunks.Count == 0)
            {
                return 0;
            }
            int leftX = chunks[0].tileOffset.x;
            for (int i = 1; i < chunks.Count; ++i)
            {
                if (leftX > chunks[i].tileOffset.x)
                    leftX = chunks[i].tileOffset.x;
            }
            return leftX;
        }
        public int GetMaxXBorder()
        {
            if (chunks.Count == 0)
            {
                return 0;
            }
            int rightX = chunks[0].tileOffset.x;
            for (int i = 1; i < chunks.Count; ++i)
            {
                if (rightX < chunks[i].tileOffset.x)
                    rightX = chunks[i].tileOffset.x;
            }
            return rightX + Graphics.CHUNK_SIZE;
        }
        public int GetMinZBorder()
        {
            if (chunks.Count == 0)
            {
                return 0;
            }
            int backZ = chunks[0].tileOffset.z;
            for (int i = 1; i < chunks.Count; ++i)
            {
                if (backZ > chunks[i].tileOffset.z)
                    backZ = chunks[i].tileOffset.z;
            }
            return backZ;
        }
        public int GetMaxZBorder()
        {
            if (chunks.Count == 0)
            {
                return 0;
            }
            int frontZ = chunks[0].tileOffset.z;
            for (int i = 1; i < chunks.Count; ++i)
            {
                if (frontZ < chunks[i].tileOffset.z)
                    frontZ = chunks[i].tileOffset.z;
            }
            return frontZ + Graphics.CHUNK_SIZE;
        }
        public int GetTopPosition(int worldX, int worldZ)
        {
            IndexPosition pos = new IndexPosition(worldX, 0, worldZ);
            Chunk chunk = GetChunk(pos);
            int top = chunk.tileManager.GetTopPosition(worldX, worldZ);
            while(true)
            {
                pos.y = top + 1;
                chunk = GetChunk(pos);
                if(chunk == null)
                {
                    break;
                }
                pos.y = chunk.tileManager.GetTopPosition(worldX, worldZ);
                if(chunk.tileManager.GetTile(pos).tileType != TileDefinition.EMPTY_TILE_TYPE)
                {
                    top = pos.y;
                }
                else
                {
                    break;
                }
            }
            return top;
        }
    }
}
